﻿/********************************************************************************
** 作者： Mick
** 邮箱： zheng_jinfan@126.com
** 主页： http://www.zhengjinfan.cn
** 创始时间：2016-2-5
** 修改人：Mick
** 修改时间：2016-2-29
** 描述：
**      资源库实现基类
**      所有资源库实现类都需要继承此类
*********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using BestEasyCMS.Core.NPoco;
using BestEasyCMS.Framework.Domain;
using BestEasyCMS.Framework.Pageing;
using BestEasyCMS.Framework.Querying;
using BestEasyCMS.Framework.UnitOfWork;
using NPoco;
using NPoco.Linq;

namespace BestEasyCMS.Repository.Base
{
    /// <summary>
    /// 资源库实现基类
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    /// <typeparam name="TEntityKey">主键类型</typeparam>
    public class RepositoryBase<T, TEntityKey> : IUnitOfWorkRepository where T : IAggregateRoot
    {
        #region Fields
        private readonly IDbBase _dbBase;
        private readonly IUnitOfWork _uow;
        #endregion

        #region Constructor
        public RepositoryBase(IDbBase dbBase, IUnitOfWork uow)
        {
            _dbBase = dbBase;
            _uow = uow;
        }
        #endregion

        #region Public Method

        #region Query
        public virtual T FindBy(TEntityKey id)
        {
            return _dbBase.SingleOrDefaultById<T>(id);
        }
        public virtual IEnumerable<T> FindAll()
        {
            return _dbBase.Fetch<T>();
        }
        public virtual IEnumerable<T> FindBy(Query query)
        {
            var sqlModel = new SqlModel();
            query.TranslateInto(sqlModel);

            return _dbBase.Query<T>(sqlModel.Sql, sqlModel.Args);
        }
        public virtual IList<T> FindBy(Query query, Paged page)
        {
            var sqlModel = new SqlModel();
            query.TranslateInto(sqlModel);

            return _dbBase.Fetch<T>(page.PageIndex, page.PageSize, sqlModel.Sql, sqlModel.Args);
        }
        public virtual Page<T> FindPageBy(Query query, Paged paged)
        {
            var sqlModel = new SqlModel();
            query.TranslateInto(sqlModel);

            return _dbBase.Page<T>(paged.PageIndex, paged.PageSize, sqlModel.Sql, sqlModel.Args);
        }
        public IQueryProviderWithIncludes<T> Query()
        {
            return _dbBase.Query<T>();
        }

        #endregion

        #region Unit Of Work
        public virtual void Update(T entity)
        {
            _uow.RegisterUpdate(entity, this);
        }
        public virtual void Insert(T entity)
        {
            _uow.RegisterAdd(entity, this);
        }
        public virtual void Delete(T entity)
        {
            _uow.RegisterDelete(entity, this);
        }
        public virtual void PersistCreationOf(IAggregateRoot entity)
        {
            _dbBase.Insert(entity);
        }
        public virtual void PersistUpdateOf(IAggregateRoot entity)
        {
            _dbBase.Update(entity);
        }
        public virtual void PersistDeletionOf(IAggregateRoot entity)
        {
            _dbBase.Delete(entity);
        }
        #endregion

        #region Insert
        public virtual void InsertBulk(IEnumerable<T> pocos)
        {
            _dbBase.InsertBulk(pocos);
        }
        #endregion

        #region Update
        public virtual int Update(T poco, IEnumerable<string> columns)
        {
            return _dbBase.Update(poco, columns);
        }
        public virtual int Update(T poco, Expression<Func<T, object>> fields)
        {
            return _dbBase.Update(poco, fields);
        }
        public virtual int Update(Query query)
        {
            var sqlModel = new SqlModel();
            query.TranslateInto(sqlModel);
            return _dbBase.Update<T>(sqlModel.Sql, sqlModel.Args);
        }


        public virtual int UpdateMany(T entity, Expression<Func<T, bool>> whereExpression)
        {
            return _dbBase.UpdateMany<T>().Where(whereExpression).Execute(entity);
        }
        #endregion

        #region Delete
        public virtual int Delete(Query query)
        {
            var sqlModel = new SqlModel();
            query.TranslateInto(sqlModel);
            return _dbBase.Delete<T>(sqlModel.Sql, sqlModel.Args);
        }
        public virtual int Delete(TEntityKey pocoOrPrimaryKey)
        {
            return _dbBase.Delete<T>(pocoOrPrimaryKey);
        }
        public virtual int DeleteMany(Expression<Func<T, bool>> whereExpression)
        {
            return _dbBase.DeleteMany<T>().Where(whereExpression).Execute();
        }
        #endregion

        #region Insert OR Update
        public virtual void Save(object poco)
        {
            _dbBase.Save<T>(poco);
        }
        #endregion

        #region Other
        public virtual bool Exists(TEntityKey primaryKey)
        {
            return _dbBase.Exists<T>(primaryKey);
        }
        public virtual bool IsNew(T poco)
        {
            return _dbBase.IsNew<T>(poco);
        }
        #endregion

        #endregion
    }
}
